long do_dom0_op(dom0_op_t *u_dom0_op)
{
long ret = 0;
- dom0_op_t op;
+ dom0_op_t *op;
if ( !IS_PRIV(current) )
return -EPERM;
- if ( copy_from_user(&op, u_dom0_op, sizeof(op)) )
- return -EFAULT;
+ if ( (op = kmalloc(sizeof(*op), GFP_KERNEL)) == NULL )
+ return -ENOMEM;
- if ( op.interface_version != DOM0_INTERFACE_VERSION )
- return -EACCES;
+ if ( copy_from_user(op, u_dom0_op, sizeof(*op)) )
+ {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if ( op->interface_version != DOM0_INTERFACE_VERSION )
+ {
+ ret = -EACCES;
+ goto out;
+ }
- switch ( op.cmd )
+ switch ( op->cmd )
{
case DOM0_BUILDDOMAIN:
{
- struct task_struct * p = find_domain_by_id(op.u.builddomain.domain);
+ struct task_struct * p = find_domain_by_id(op->u.builddomain.domain);
ret = -EINVAL;
if ( p != NULL )
{
- ret = final_setup_guestos(p, &op.u.builddomain);
+ ret = final_setup_guestos(p, &op->u.builddomain);
put_task_struct(p);
}
}
case DOM0_STARTDOMAIN:
{
- struct task_struct * p = find_domain_by_id(op.u.startdomain.domain);
+ struct task_struct * p = find_domain_by_id(op->u.startdomain.domain);
ret = -EINVAL;
if ( p != NULL )
{
case DOM0_STOPDOMAIN:
{
- ret = stop_other_domain(op.u.stopdomain.domain);
+ ret = stop_other_domain(op->u.stopdomain.domain);
}
break;
if ( p == NULL )
goto exit_create;
- if ( op.u.createdomain.name[0] )
+ if ( op->u.createdomain.name[0] )
{
- strncpy (p->name, op.u.createdomain.name, MAX_DOMAIN_NAME);
+ strncpy (p->name, op->u.createdomain.name, MAX_DOMAIN_NAME);
p->name[MAX_DOMAIN_NAME - 1] = 0;
}
- ret = alloc_new_dom_mem(p, op.u.createdomain.memory_kb);
+ ret = alloc_new_dom_mem(p, op->u.createdomain.memory_kb);
if ( ret != 0 )
{
__kill_domain(p);
ret = p->domain;
- op.u.createdomain.domain = ret;
- copy_to_user(u_dom0_op, &op, sizeof(op));
+ op->u.createdomain.domain = ret;
+ copy_to_user(u_dom0_op, op, sizeof(*op));
exit_create:
spin_unlock_irq(&create_dom_lock);
case DOM0_DESTROYDOMAIN:
{
- unsigned int dom = op.u.destroydomain.domain;
- int force = op.u.destroydomain.force;
+ unsigned int dom = op->u.destroydomain.domain;
+ int force = op->u.destroydomain.force;
ret = (dom == IDLE_DOMAIN_ID) ? -EPERM : kill_other_domain(dom, force);
}
break;
case DOM0_PINCPUDOMAIN:
{
- struct task_struct * p = find_domain_by_id(op.u.pincpudomain.domain);
- int cpu = op.u.pincpudomain.cpu;
+ struct task_struct * p = find_domain_by_id(op->u.pincpudomain.domain);
+ int cpu = op->u.pincpudomain.cpu;
ret = -EINVAL;
if ( p != NULL )
{
case DOM0_BVTCTL:
{
- unsigned long ctx_allow = op.u.bvtctl.ctx_allow;
+ unsigned long ctx_allow = op->u.bvtctl.ctx_allow;
ret = sched_bvtctl(ctx_allow);
}
break;
case DOM0_ADJUSTDOM:
{
- unsigned int dom = op.u.adjustdom.domain;
- unsigned long mcu_adv = op.u.adjustdom.mcu_adv;
- unsigned long warp = op.u.adjustdom.warp;
- unsigned long warpl = op.u.adjustdom.warpl;
- unsigned long warpu = op.u.adjustdom.warpu;
+ unsigned int dom = op->u.adjustdom.domain;
+ unsigned long mcu_adv = op->u.adjustdom.mcu_adv;
+ unsigned long warp = op->u.adjustdom.warp;
+ unsigned long warpl = op->u.adjustdom.warpl;
+ unsigned long warpu = op->u.adjustdom.warpu;
ret = -EPERM;
if ( dom != IDLE_DOMAIN_ID )
case DOM0_GETMEMLIST:
{
int i;
- struct task_struct *p = find_domain_by_id(op.u.getmemlist.domain);
- unsigned long max_pfns = op.u.getmemlist.max_pfns;
+ struct task_struct *p = find_domain_by_id(op->u.getmemlist.domain);
+ unsigned long max_pfns = op->u.getmemlist.max_pfns;
unsigned long pfn;
- unsigned long *buffer = op.u.getmemlist.buffer;
+ unsigned long *buffer = op->u.getmemlist.buffer;
struct list_head *list_ent;
ret = -EINVAL;
}
spin_unlock(&p->page_list_lock);
- op.u.getmemlist.num_pfns = i;
- copy_to_user(u_dom0_op, &op, sizeof(op));
+ op->u.getmemlist.num_pfns = i;
+ copy_to_user(u_dom0_op, op, sizeof(*op));
put_task_struct(p);
}
read_lock_irqsave (&tasklist_lock, flags);
while ( (p = p->next_task) != &idle0_task )
- if ( !is_idle_task(p) && (p->domain >= op.u.getdomaininfo.domain) )
+ if ( !is_idle_task(p) &&
+ (p->domain >= op->u.getdomaininfo.domain) )
break;
if ( p == &idle0_task )
}
else
{
- op.u.getdomaininfo.domain = p->domain;
- strcpy (op.u.getdomaininfo.name, p->name);
- op.u.getdomaininfo.processor = p->processor;
- op.u.getdomaininfo.has_cpu = p->has_cpu;
- op.u.getdomaininfo.state = DOMSTATE_ACTIVE;
+ op->u.getdomaininfo.domain = p->domain;
+ strcpy (op->u.getdomaininfo.name, p->name);
+ op->u.getdomaininfo.processor = p->processor;
+ op->u.getdomaininfo.has_cpu = p->has_cpu;
+ op->u.getdomaininfo.state = DOMSTATE_ACTIVE;
if ( (p->state == TASK_STOPPED) || (p->state == TASK_DYING) )
- op.u.getdomaininfo.state = DOMSTATE_STOPPED;
- op.u.getdomaininfo.hyp_events = p->hyp_events;
- op.u.getdomaininfo.mcu_advance = p->mcu_advance;
- op.u.getdomaininfo.tot_pages = p->tot_pages;
- op.u.getdomaininfo.cpu_time = p->cpu_time;
- op.u.getdomaininfo.shared_info_frame =
+ op->u.getdomaininfo.state = DOMSTATE_STOPPED;
+ op->u.getdomaininfo.hyp_events = p->hyp_events;
+ op->u.getdomaininfo.mcu_advance = p->mcu_advance;
+ op->u.getdomaininfo.tot_pages = p->tot_pages;
+ op->u.getdomaininfo.cpu_time = p->cpu_time;
+ op->u.getdomaininfo.shared_info_frame =
__pa(p->shared_info) >> PAGE_SHIFT;
if ( p->state == TASK_STOPPED )
{
rmb(); /* Ensure that we see saved register state. */
- op.u.getdomaininfo.ctxt.flags = 0;
- memcpy(&op.u.getdomaininfo.ctxt.i386_ctxt,
+ op->u.getdomaininfo.ctxt.flags = 0;
+ memcpy(&op->u.getdomaininfo.ctxt.i386_ctxt,
&p->shared_info->execution_context,
sizeof(p->shared_info->execution_context));
if ( p->flags & PF_DONEFPUINIT )
- op.u.getdomaininfo.ctxt.flags |= ECF_I387_VALID;
- memcpy(&op.u.getdomaininfo.ctxt.i387_ctxt,
+ op->u.getdomaininfo.ctxt.flags |= ECF_I387_VALID;
+ memcpy(&op->u.getdomaininfo.ctxt.i387_ctxt,
&p->thread.i387,
sizeof(p->thread.i387));
- memcpy(&op.u.getdomaininfo.ctxt.trap_ctxt,
+ memcpy(&op->u.getdomaininfo.ctxt.trap_ctxt,
p->thread.traps,
sizeof(p->thread.traps));
if ( (p->thread.fast_trap_desc.a == 0) &&
(p->thread.fast_trap_desc.b == 0) )
- op.u.getdomaininfo.ctxt.fast_trap_idx = 0;
+ op->u.getdomaininfo.ctxt.fast_trap_idx = 0;
else
- op.u.getdomaininfo.ctxt.fast_trap_idx =
+ op->u.getdomaininfo.ctxt.fast_trap_idx =
p->thread.fast_trap_idx;
- op.u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base;
- op.u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents;
- op.u.getdomaininfo.ctxt.gdt_ents = 0;
+ op->u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base;
+ op->u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents;
+ op->u.getdomaininfo.ctxt.gdt_ents = 0;
if ( GET_GDT_ADDRESS(p) == GDT_VIRT_START )
{
for ( i = 0; i < 16; i++ )
- op.u.getdomaininfo.ctxt.gdt_frames[i] =
+ op->u.getdomaininfo.ctxt.gdt_frames[i] =
l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]);
- op.u.getdomaininfo.ctxt.gdt_ents =
+ op->u.getdomaininfo.ctxt.gdt_ents =
(GET_GDT_ENTRIES(p) + 1) >> 3;
}
- op.u.getdomaininfo.ctxt.ring1_ss = p->thread.ss1;
- op.u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1;
- op.u.getdomaininfo.ctxt.pt_base =
+ op->u.getdomaininfo.ctxt.ring1_ss = p->thread.ss1;
+ op->u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1;
+ op->u.getdomaininfo.ctxt.pt_base =
pagetable_val(p->mm.pagetable);
- memcpy(op.u.getdomaininfo.ctxt.debugreg,
+ memcpy(op->u.getdomaininfo.ctxt.debugreg,
p->thread.debugreg,
sizeof(p->thread.debugreg));
- op.u.getdomaininfo.ctxt.event_callback_cs = p->event_selector;
- op.u.getdomaininfo.ctxt.event_callback_eip = p->event_address;
- op.u.getdomaininfo.ctxt.failsafe_callback_cs =
+ op->u.getdomaininfo.ctxt.event_callback_cs =
+ p->event_selector;
+ op->u.getdomaininfo.ctxt.event_callback_eip =
+ p->event_address;
+ op->u.getdomaininfo.ctxt.failsafe_callback_cs =
p->failsafe_selector;
- op.u.getdomaininfo.ctxt.failsafe_callback_eip =
+ op->u.getdomaininfo.ctxt.failsafe_callback_eip =
p->failsafe_address;
}
}
read_unlock_irqrestore(&tasklist_lock, flags);
- copy_to_user(u_dom0_op, &op, sizeof(op));
+ copy_to_user(u_dom0_op, op, sizeof(*op));
}
break;
case DOM0_GETPAGEFRAMEINFO:
{
struct pfn_info *page;
- unsigned long pfn = op.u.getpageframeinfo.pfn;
- unsigned int dom = op.u.getpageframeinfo.domain;
+ unsigned long pfn = op->u.getpageframeinfo.pfn;
+ unsigned int dom = op->u.getpageframeinfo.domain;
struct task_struct *p;
ret = -EINVAL;
{
ret = 0;
- op.u.getpageframeinfo.type = NONE;
+ op->u.getpageframeinfo.type = NONE;
if ( (page->type_and_flags & PGT_count_mask) != 0 )
{
switch ( page->type_and_flags & PGT_type_mask )
{
case PGT_l1_page_table:
- op.u.getpageframeinfo.type = L1TAB;
+ op->u.getpageframeinfo.type = L1TAB;
break;
case PGT_l2_page_table:
- op.u.getpageframeinfo.type = L2TAB;
+ op->u.getpageframeinfo.type = L2TAB;
break;
}
}
put_task_struct(p);
- copy_to_user(u_dom0_op, &op, sizeof(op));
+ copy_to_user(u_dom0_op, op, sizeof(*op));
}
break;
case DOM0_IOPL:
{
extern long do_iopl(unsigned int, unsigned int);
- ret = do_iopl(op.u.iopl.domain, op.u.iopl.iopl);
+ ret = do_iopl(op->u.iopl.domain, op->u.iopl.iopl);
}
break;
case DOM0_MSR:
{
- if ( op.u.msr.write )
+ if ( op->u.msr.write )
{
- msr_cpu_mask = op.u.msr.cpu_mask;
- msr_addr = op.u.msr.msr;
- msr_lo = op.u.msr.in1;
- msr_hi = op.u.msr.in2;
+ msr_cpu_mask = op->u.msr.cpu_mask;
+ msr_addr = op->u.msr.msr;
+ msr_lo = op->u.msr.in1;
+ msr_hi = op->u.msr.in2;
smp_call_function(write_msr_for, NULL, 1, 1);
write_msr_for(NULL);
}
else
{
- msr_cpu_mask = op.u.msr.cpu_mask;
- msr_addr = op.u.msr.msr;
+ msr_cpu_mask = op->u.msr.cpu_mask;
+ msr_addr = op->u.msr.msr;
smp_call_function(read_msr_for, NULL, 1, 1);
read_msr_for(NULL);
- op.u.msr.out1 = msr_lo;
- op.u.msr.out2 = msr_hi;
- copy_to_user(u_dom0_op, &op, sizeof(op));
+ op->u.msr.out1 = msr_lo;
+ op->u.msr.out2 = msr_hi;
+ copy_to_user(u_dom0_op, op, sizeof(*op));
}
ret = 0;
}
case DOM0_DEBUG:
{
extern void pdb_do_debug(dom0_op_t *);
- pdb_do_debug(&op);
- copy_to_user(u_dom0_op, &op, sizeof(op));
+ pdb_do_debug(op);
+ copy_to_user(u_dom0_op, op, sizeof(*op));
ret = 0;
}
break;
case DOM0_SETTIME:
{
- do_settime(op.u.settime.secs,
- op.u.settime.usecs,
- op.u.settime.system_time);
+ do_settime(op->u.settime.secs,
+ op->u.settime.usecs,
+ op->u.settime.system_time);
ret = 0;
}
break;
case DOM0_READCONSOLE:
{
- extern long read_console_ring(unsigned long, unsigned int, unsigned int);
- ret = read_console_ring(op.u.readconsole.str,
- op.u.readconsole.count,
- op.u.readconsole.cmd);
+ extern long read_console_ring(unsigned long,
+ unsigned int, unsigned int);
+ ret = read_console_ring(op->u.readconsole.str,
+ op->u.readconsole.count,
+ op->u.readconsole.cmd);
}
break;
}
+ out:
+ kfree(op);
return ret;
}